﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;

namespace PackTracker.Mobile.Negocio.RFID
{
    public class Device
    {
        protected TcpClient     tcpClient       = null;
        protected NetworkStream networkStream   = null;
        protected bool          connected       = false;

        #region Properties
        protected string user;

        public string User
        {
            get { return user; }
            set { user = value; }
        }

        protected string password;

        public string Password
        {
            set { password = value; }
        }

        protected string server;

        public string Server
        {
            get { return server; }
            set { server = value; }
        }

        protected int port;

        public int Port
        {
            get { return port; }
            set { port = value; }
        }
        #endregion

        public void Connect()
        {
            connect();
        }

        public void Connect(string user, string password)
        {
            this.user       = user;
            this.password   = password;

            connect();
        }

        public void Connect(string user, string password, string ip, int port)
        {
            this.user       = user;
            this.password   = password;
            this.server     = ip;
            this.port       = port;

            connect();
        }

        public void Disconnect()
        {
            if (connected)
            {
                executeCommand("q");

                networkStream.Close();
                tcpClient.Close();

                connected = false;
            }
        }

        public List<Tag> GetTagList()
        {
            if (!connected)
                throw new Exception("Must be connected");

            string result = executeCommand("get TagList");

            List<Tag> tags = new List<Tag>();

            if (result.IndexOf("(No tags)") == -1)
            {
                Regex regexp = new Regex("Tag:.*[^\r\n]");
                MatchCollection maches = regexp.Matches(result);

                foreach (Match match in maches)
                {
                    tags.Add(new Tag(match.Value));
                }
            }

            return tags;
        }

        #region Private Methods 

        private void connect()
        {
            #region Verify all configurations
            if (this.user.Equals(""))
                throw new Exception("Invalid User");

            if (this.password.Equals(""))
                throw new Exception("Invalid Password");

            if (this.server.Equals(""))
                throw new Exception("Invalid Server");

            if (this.port.Equals(""))
                throw new Exception("Invalid Port");
            #endregion

            tcpClient = new TcpClient(this.server, this.port);
            networkStream = tcpClient.GetStream();

            executeCommand(this.user); //User
            string retorno = executeCommand(this.password); //Password

            //Check if user and password are correct
            if (retorno.IndexOf("Error") > -1)
            {
                throw new Exception(retorno);
            }

            connected = true;
        }

        private string read()
        {
            StreamReader streamReader = new StreamReader(networkStream);
            char[] chars = new char[2048];
            streamReader.Read(chars, 0, chars.Length);

            string message = "";

            for (int i = 0; i < chars.Length; i++)
            {
                message += chars[i].ToString() == "\0" ? "" : chars[i].ToString();
            }

            return message;

        }

        private string executeCommand(string command)
        {
            StreamWriter streamWriter = new StreamWriter(networkStream);
            streamWriter.WriteLine(command);
            streamWriter.Flush();

            return read();
        }

        #endregion
    }
}
